//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.yexx.idGenerator;

import com.yexx.uid.IdGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;

import javax.annotation.PostConstruct;
import java.util.List;

public class IncrIdGenerator implements IdGenerator {
    private static final String ID_GENERATOR_KEY = "common:id_generator";
    private static volatile long ID_OFFSET = 100000000000000L;
    private static final long ID_MAX = 1000000000000000L;
    @Autowired
    RedisTemplate<String, Object> redisTemplate;

    public IncrIdGenerator() {
    }

    @PostConstruct
    void init() {
        RedisAtomicLong entityIdCounter = new RedisAtomicLong("common:id_generator", this.redisTemplate.getConnectionFactory());
        Long id = entityIdCounter.getAndIncrement();
        if (id != null && id >= ID_OFFSET) {
            if (id > ID_MAX) {
                throw new RuntimeException("当前主键偏移量错误");
            }
        } else {
            ID_OFFSET = this.reset();
        }

    }

    private Long reset() {
        Long now = this.redisTemplate.getRequiredConnectionFactory().getConnection().time();
        Long id = now * 100L;
        this.setIncr(ID_GENERATOR_KEY, id);
        return id;
    }

    public Long generate() {
        return this.getIncr(ID_GENERATOR_KEY);
    }

    public List<Long> generateBatch(int count) {
        throw new RuntimeException("不支持");
    }

    private Long getIncr(String key) {
        RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, this.redisTemplate.getConnectionFactory());
        Long increment = entityIdCounter.getAndIncrement();
        if (increment < ID_OFFSET) {
            increment = this.reset();
        } else if (increment > ID_MAX) {
            throw new RuntimeException("当前主键偏移量错误");
        }

        ID_OFFSET = increment;
        return increment;
    }

    private void setIncr(String key, Long value) {
        RedisAtomicLong counter = new RedisAtomicLong(key, this.redisTemplate.getConnectionFactory());
        counter.set(value);
    }
}
